﻿#region Namespaces

using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;

#endregion

namespace Vibstudio.X4NET.Globalization
{
    public sealed class Labeler : LabelingProviderBase, ILabeling
    {
        #region Ctor(s)

        public Labeler(string lang = "", string langFileName = "", string appLangKey = "")
        {
            AppLang = lang;
            AppLangFileName = string.IsNullOrEmpty(langFileName) ? DefaultAppLangKey : langFileName;
            AppLangKey = string.IsNullOrEmpty(appLangKey) ? DefaultAppLangKey : appLangKey;
        }

        public Labeler()
            : this(string.Empty)
        {
        }

        #endregion

        #region ILabelingProvider implementation

        public IList<DictionaryEntry> LabelDictionary(string lang = "")
        {
            List<DictionaryEntry> entries = new List<DictionaryEntry>();

            foreach (ILabelingProvider labelingProvider in GetLabelingProviders())
            {
                entries.AddRange(labelingProvider.LabelDictionary());
            }

            return entries;
        }

        public string this[string name, string lang = ""]
        {
            get
            {
                foreach (ILabelingProvider labelingProvider in GetLabelingProviders())
                {
                    string label = labelingProvider[name, lang];
                    if (!string.IsNullOrEmpty(label))
                    {
                        return label;
                    }
                }

                return Labels.ResourceManager.GetString(name);
            }
        }

        #endregion

        #region ILabeling implementation

        public Label FileNotFound(string fileName)
        {
            string label = this["FileNotFoundFormat"];
            return Label.Create(!string.IsNullOrEmpty(label) ? string.Format(label, fileName) : string.Format(Labels.FileNotFoundFormat, fileName));
        }

        public Label ConversionFailed
        {
            get
            {
                string label = this["ConversionFailed"];
                return Label.Create(!string.IsNullOrEmpty(label) ? label : Labels.ConversionFailed);
            }
        }

        public Label ConversionPerformed
        {
            get
            {
                string label = this["ConversionPerformed"];
                return Label.Create(!string.IsNullOrEmpty(label) ? label : Labels.ConversionPerformed);
            }
        }

        public Label CsvMalformed
        {
            get
            {
                string label = this["CsvMalformed"];
                return Label.Create(!string.IsNullOrEmpty(label) ? label : Labels.CsvMalformed);
            }
        }

        public Label PositionalExtractionRequired
        {
            get
            {
                string label = this["PositionalExtractionRequired"];
                return Label.Create(!string.IsNullOrEmpty(label) ? label : Labels.PositionalExtractionRequired);
            }
        }

        #endregion

        #region Helpers

        private IList<ILabelingProvider> GetLabelingProviders()
        {
            IList<ILabelingProvider> labelingProviders = new List<ILabelingProvider>();

            Type interfaceType = typeof(ILabelingProvider);
            Assembly currentAssembly = Assembly.GetExecutingAssembly();
            Type[] types = currentAssembly.GetTypes();

            foreach (var type in types)
            {
                if (interfaceType.IsAssignableFrom(type) && type.IsPublic && !type.IsInterface && !type.FullName.Equals(GetType().FullName))
                {
                    labelingProviders.Add((ILabelingProvider)currentAssembly.CreateInstance(type.FullName, false));
                }
            }

            return labelingProviders;
        }

        #endregion
    }
}
